class Dbln {
  constructor(element, next = null, previous = null) {
    this.element = element;
    this.next = next;
    this.previous = previous;
  }
}

class DoublyLinkedList {
  /**
   * @param {Function} [comparatorFunction]
   */
  constructor(comparatorFunction) {
    /** @var DoublyLinkedListNode */
    this.head = null;

    /** @var DoublyLinkedListNode */
    this.tail = null;

  }

  /**
   * @param {*} value
   * @return {DoublyLinkedList}
   */
  prepend(value) {

  }

  /**
   * @param {*} value
   * @return {DoublyLinkedList}
   */
  append(value) {
    const newNode = new Dbln(value);
    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    }

    // 改变当前节点的next指向
    this.tail.next = newNode;

    // 新的节点指向上一个指针
    newNode.previous = this.tail;

    //改变最后一个指针指向
    this.tail = newNode;
  }

  /**
   * @param {*} value
   * @return {DoublyLinkedListNode}
   */
  delete(value) {
    if (!this.head) {
      return null;
    }

    let deletedNode = null;
    //从第二个节点开始比较
    let currentNode = this.head;

    while (currentNode) {
      if (currentNode.element === value) {
        deletedNode = currentNode;
        if (deletedNode === this.head) {
          this.head = this.head.next;
          //如果第二个节点存在。头节点的上一个节点始终为空
          if (this.head) {
            this.head.previous = null;
          }
        } else if (deletedNode === this.tail) {
          this.tail = this.tail.previous;
          // 尾节点始终下一个节点指向null
          this.tail.next = null;
        } else {
          const previousNode = deletedNode.previous;
          const nextNode = deletedNode.next;

          // 删除中间节点后上一个节点的
          previousNode.next = nextNode;
          nextNode.previous = previousNode;
        }
        return deletedNode;
      } else {
        currentNode = currentNode.next;
      }
    }

    return deletedNode;
  }

  /**
   * @param {Object} findParams
   * @param {*} findParams.value
   * @param {function} [findParams.callback]
   * @return {DoublyLinkedListNode}
   */
  find(value = undefined) {
    if (!this.head) {
      return null;
    }

    let currentNode = this.head;

    while (currentNode) {
      if (currentNode.element === value) {
        return currentNode;
      }
      currentNode = currentNode.next;
    }

    return null;
  }

  /**
   * @return {DoublyLinkedListNode[]}
   */
  toArray() {
    const nodes = [];

    let currentNode = this.head;
    while (currentNode) {
      nodes.push(currentNode);
      currentNode = currentNode.next;
    }

    return nodes;
  }

  /**
   * @param {*[]} values - Array of values that need to be converted to linked list.
   * @return {DoublyLinkedList}
   */
  fromArray(values) {
    values.forEach(value => this.append(value));

    return this;
  }

  /**
   * @param {function} [callback]
   * @return {string}
   */
  toString(callback) {
    return this.toArray().map(node => node.toString(callback)).toString();
  }

  /**
   * Reverse a linked list.
   * @returns {DoublyLinkedList}
   */
  reverse() {

  }
}

let myLink = new DoublyLinkedList();
myLink.append('A')
myLink.append('B')
myLink.append('C')
myLink.append('E')
myLink.toArray();
myLink.delete('B')
myLink.toArray();
// myLink.insert(3, 'D')
// myLink.insert(5, 'F')
// myLink.insert(0, 'G')
// console.log(myLink.toString()) //GABCDEF
// myLink.removeAt(0) //删除G
// myLink.removeAt(5) //删除F
// console.log(myLink.remove()) //删除E
// console.log(myLink.toString()) // ABCD
// myLink.append('D') //向尾部增加D
// console.log(myLink.toString()) //ABCDD
// console.log(myLink.removeEle('D')) //删除所有D,打印删除D的个数 2
// console.log(myLink.toString()) //ABC
// console.log(myLink.indexOf('B')) //打印B的位置 1
// console.log(myLink.size()) //打印链表的长度 3
// console.log(myLink.getHead()) //A
// console.log(myLink.getTail()) //C